from sklearn.decomposition import KernelPCA
from sklearn.metrics.pairwise import *
import scipy.linalg
import numpy as np

def fpp_kernel(X, Y=None, degree=0.6, gamma=None, coef0=1):
    """
    Compute the fpp kernel between X and Y::

        K(X, Y) = (gamma <X, Y> + coef0)^degree

    Parameters
    ----------
    X : array of shape (n_samples_1, n_features)

    Y : array of shape (n_samples_2, n_features)

    degree : (0.0, 1.0)

    Returns
    -------
    Gram matrix : array of shape (n_samples_1, n_samples_2)
    """
    X, Y = check_pairwise_arrays(X, Y)
    if gamma is None:
        gamma = 1.0 / X.shape[1]

    K = linear_kernel(X, Y)
    K *= gamma
    K += coef0

    new_K= scipy.linalg.sqrtm(K)
    return K

class FppKPCA(KernelPCA):
    def __init__(self, n_components=None, gamma=None, degree=0.5, coef0=0, \
                 alpha=1.0, fit_inverse_transform=False, eigen_solver='auto', \
                 tol=0, max_iter=None, remove_zero_eig=False):
       KernelPCA.__init__(self, n_components=n_components, kernel='fpp', gamma=gamma, \
                          degree=degree, coef0=coef0, kernel_params=None, alpha=alpha, \
                          fit_inverse_transform=fit_inverse_transform, eigen_solver=eigen_solver, \
                          tol=tol, max_iter=max_iter, remove_zero_eig=remove_zero_eig)

    def _get_kernel(self, X, Y=None):
        return fpp_kernel(X, Y, self.degree, self.gamma, self.coef0)
